# -*- coding:utf-8 -*-
from fastapi import Request, HTTPException
from sqlalchemy.exc import OperationalError
from sqlalchemy import select, text, delete, update
from app.entity.system import SysUser, SysUserRole, SysUserPost
from core.curd import CRUDBase, IBaseDao
from typing import List
from core.utils import code_number, en_password_md5

BaseDao = CRUDBase(SysUser)


class SysUserDao(IBaseDao):
    """
    测试模块服务层
    """
    def __init__(self, req:Request):
        self.db_session = req.app.state.db_async_session
        self.base = CRUDBase(SysUser)

    async def select_by_name(self, name:str):
        async with self.db_session() as db:
            try:
                data = await db.execute(select(SysUser).filter(SysUser.username == name))
                return data.scalars().first()
            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()

    async def update_user(self, post):
        async with self.db_session() as db:
            try:
                user_id = post.get("id")
                postIds = post.get("postIdList")
                roleIds = post.get("roleIdList")

                del post['id']
                del post['postIdList']
                del post['roleIdList']
                
                if post.get("password") is not None and post.get('password') != '':
                    post['salt'] = code_number(4)
                    post['password'] = en_password_md5(post['password'], post['salt'])
                else:
                    del post['password']

                result = await db.execute(update(SysUser).where(SysUser.id == user_id).values(**post))

                await db.flush()

                await db.execute(delete(SysUserPost).where(SysUserPost.user_id == user_id))
                for postId in postIds:
                    d = SysUserPost(user_id=user_id, post_id=postId)
                    db.add(d)

                await db.execute(delete(SysUserRole).where(SysUserRole.user_id == user_id))
                for roleId in roleIds:
                    d = SysUserRole(user_id=user_id, role_id=roleId)
                    db.add(d)

                await db.commit()

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()

    async def create_user(self, post: dict):
        async with self.db_session() as db:
            try:
                postIds = post.get("postIdList")
                roleIds = post.get("roleIdList")

                del post['postIdList']
                del post['roleIdList']

                create_data = SysUser(**post)
                db.add(create_data)
                await db.flush()

                res = await db.execute(text("SELECT LAST_INSERT_ID() as last_id"))
                user_id = res.scalars().first()

                for postId in postIds:
                    d = SysUserPost(user_id=user_id, post_id=postId)
                    db.add(d)

                for roleId in roleIds:
                    d = SysUserRole(user_id=user_id, role_id=roleId)
                    db.add(d)

                await db.commit()

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()

    async def delete_user(self, ids:List[int]):

        async with self.db_session() as db:
            try:
                result = await db.execute(delete(SysUser).where(SysUser.id.in_(ids)))
                result = await db.execute(delete(SysUserRole).where(SysUserRole.user_id.in_(ids)))
                result = await db.execute(delete(SysUserPost).where(SysUserPost.user_id.in_(ids)))

                await db.commit()
            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()
        return []

    async def get_user_role(self, id:int):
        async with self.db_session() as db:
            try:
                d = await db.execute(select(SysUserRole.role_id).filter(SysUserRole.user_id == id))
                return [v[0] for v in d.fetchall()]

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()

    async def get_user_post(self, id:int):
        async with self.db_session() as db:
            try:
                d = await db.execute(select(SysUserPost.post_id).filter(SysUserPost.user_id == id))
                return [v[0] for v in d.fetchall()]

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()

    async def get_user_dept_info(self, id:int):
        async with self.db_session() as db:
            try:
                return []

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()

    async def get_user_post_info(self, id:int):
        async with self.db_session() as db:
            try:
                return []

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()

    async def get_user_role_info(self, id:int):
        async with self.db_session() as db:
            try:
                return []

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e) )
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e) )
            finally:
                await db.close()



    @classmethod
    async def instance(cls, req:Request):
        return cls(req)



